using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace EffectGenerator
{
    public abstract class TypeSafeParameterCollection<T> : IEnumerable<T>
    {
        private EffectParameterCollection effectParameterCollection;
        protected EffectParameterCollection EffectParameterCollection
        {
            get
            {
                return this.effectParameterCollection;
            }
        }

        public TypeSafeParameterCollection(EffectParameterCollection effectParameterCollection)
        {
            this.effectParameterCollection = effectParameterCollection;
        }

        protected internal abstract T GetValue(EffectParameter effectParameter);
        protected internal abstract void SetValue(EffectParameter effectParameter, T value);

        public IEnumerator<T> GetEnumerator()
        {
            foreach (EffectParameter effectParameter in this.effectParameterCollection)
                yield return this.GetValue(effectParameter);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public int Count
        {
            get
            {
                return this.effectParameterCollection.Count;
            }
        }

        public T this[int index]
        {
            get
            {
                return this.GetValue(this.effectParameterCollection[index]);
            }

            set
            {
                this.SetValue(this.effectParameterCollection[index], value);
            }
        }
    }

    public sealed class MatrixParameterCollection : TypeSafeParameterCollection<Matrix>
    {
        public MatrixParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override Matrix GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueMatrix();
        }

        protected internal override void SetValue(EffectParameter effectParameter, Matrix value)
        {
            effectParameter.SetValue(value);
        }
    }

    public sealed class StringParameterCollection : TypeSafeParameterCollection<String>
    {
        public StringParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override String GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueString();
        }

        protected internal override void SetValue(EffectParameter effectParameter, String value)
        {
            effectParameter.SetValue(value);
        }
    }

    public sealed class SingleParameterCollection : TypeSafeParameterCollection<Single>
    {
        public SingleParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override Single GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueSingle();
        }

        protected internal override void SetValue(EffectParameter effectParameter, Single value)
        {
            effectParameter.SetValue(value);
        }
    }

    public sealed class Vector2ParameterCollection : TypeSafeParameterCollection<Vector2>
    {
        public Vector2ParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override Vector2 GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueVector2();
        }

        protected internal override void SetValue(EffectParameter effectParameter, Vector2 value)
        {
            effectParameter.SetValue(value);
        }
    }

    public sealed class Vector3ParameterCollection : TypeSafeParameterCollection<Vector3>
    {
        public Vector3ParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override Vector3 GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueVector3();
        }

        protected internal override void SetValue(EffectParameter effectParameter, Vector3 value)
        {
            effectParameter.SetValue(value);
        }
    }

    public sealed class Vector4ParameterCollection : TypeSafeParameterCollection<Vector4>
    {
        public Vector4ParameterCollection(EffectParameterCollection effectParameterCollection)
            : base(effectParameterCollection)
        {
        }

        protected internal override Vector4 GetValue(EffectParameter effectParameter)
        {
            return effectParameter.GetValueVector4();
        }

        protected internal override void SetValue(EffectParameter effectParameter, Vector4 value)
        {
            effectParameter.SetValue(value);
        }
    }
}
